const WebSocketAwait = require('ws-await');
const { EventEmitter } = require('events');
const awaitTimeout = 30000;

class MCSClient extends EventEmitter {
	constructor(props) {
		super(props);
		this.host = props.host;
		this.port = props.port;
		this.reSetRetry();
		this.createSocket(props);
		this.queue = []
		this._isReady = false
	}

	reSetRetry(options) {
		this.retry = Object.assign({ delay: 2000, timeout: 60000, total: 0, timer: undefined, attempts: 0 }, options);
	}

	createSocket() {
		this.ws = new WebSocketAwait(`ws://${this.host}:${this.port}`, { awaitTimeout });
		this.ws.on('open', (...args) => {
			this._isReady = true
			this.emit('open', args);
			this.reSetRetry();
			for (const msg of this.queue) {
				let reslove = msg['_message_resolve']
				let reject = msg['_message_reject']
				delete msg['_message_resolve']
				delete msg['_message_reject']
				this.ws.sendAwait(msg).then(reslove).catch(reject)
			}
			this.queue = []
		});
		this.ws.once('close', () => {
			this._connection_gone('close')
		})

		this.ws.once('error', (err) => {
			this._connection_gone('error', err)
		})

		this.ws.once('end', () => {
			this._connection_gone('end')
		})
	}


	get Ready() {
		return this._isReady
	}

	async sent(msg) {
		if (this.Ready) {
			return this.ws.sendAwait(msg)
		}
		return new Promise((resolve, reject) => {
			msg['_message_resolve'] = resolve
			msg['_message_reject'] = reject
			this.queue.push(msg)
		})
	}

	_retry_connection() {
		this.retry.total += this.retry.delay;
		this.retry.attempts += 1;
		this.createSocket()
		this.retry.timer = undefined;

	}

	_connection_gone(why, error) {
		if (this.retry.timer) {
			return;
		}
		console.log('MCSClient connection is gone from ' + why + ' event.');
		this._isReady = false
		let re = this.retry;
		if (why === 'error') {
			this.emit('error', error)
			return re.timer = setTimeout(this._retry_connection.bind(this), re.delay);
		}
		// if (re.total > re.timeout) {
		// 	this.emit('error', error)
		// 	return;
		// }
		// re.timer = setTimeout(this._retry_connection.bind(this), re.delay);
	}
}

module.exports = MCSClient
